¿Es posible usar una function como el estado de mi React Component?
código de ejemplo aquí:
// typescript type OoopsFunction = () => void; export function App() { const [ooops, setOoops] = React.useState<OoopsFunction>( () => console.log('default ooops') ); return ( <div> <div onClick={ ooops }> Show Ooops </div> <div onClick={() => { setOoops(() => console.log('other ooops')) }}> change oops </div> </div> ) } pero no funciona... el defaultOoops se invocará desde el principio, y al hacer clic en change oops , los otrher ooops se registrarán en la consola inmediatamente y no se registrarán después de hacer clic en Show Ooops nuevamente.
por qué ?
¿Es posible para mí usar una función como estado de mi componente?
¿O bien React tiene sus formas especiales de procesar the function state ?
Es posible establecer una función en el estado usando ganchos, pero debido a que el estado se puede inicializar y actualizar con una función que devuelve el estado inicial o el estado actualizado, debe proporcionar una función que a su vez devuelva la función que desea poner. Expresar.
const { useState } = React; function App() { const [ooops, setOoops] = useState(() => () => console.log("default ooops")); return ( <div> <button onClick={ooops}>Show Ooops</button> <button onClick={() => { setOoops(() => () => console.log("other ooops")); }} > change oops </button> </div> ); } ReactDOM.render(<App />, document.getElementById("root")); <script src="https://unpkg.com/react@16/umd/react.development.js"></script> <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> <div id="root"></div> Sí, es posible utilizar una función como estado del componente React. Para hacer esto, debe usar una función que devuelva su función en React.useState :
const [ooops, setOoops] = React.useState<OoopsFunction>( () => () => console.log('default ooops') ); // or const yourFunction = () => console.log('default ooops'); const [ooops, setOoops] = React.useState<OoopsFunction>( () => yourFunction );Para actualizar su función, también debe usar una función que devuelva su función :
setOoops(() => () => console.log("other ooops")); // or const otherFunction = () => console.log("other ooops"); setOoops(() => otherFunction);React.useState La firma de useState en React con tipos es
function useState<S>(initialState: S | (() => S)): [S, Dispatch<SetStateAction<S>>];Muestra que hay dos formas de establecer el valor inicial en su estado:
React.useState(0) - valor inicial 0 ),React.useState(() => 0) - valor inicial también 0 ). Importante tener en cuenta: si proporciona una función en React.useState , esta función se ejecuta cuando se ejecuta React.useState y el valor devuelto se almacena como el estado inicial.
El problema aquí es que si desea almacenar una función como estado, no puede proporcionarla como estado inicial, ya que esto da como resultado que la función se ejecute y su valor de retorno se almacene como estado en lugar de la función misma . Por eso cuando escribes
const [ooops, setOoops] = React.useState<OoopsFunction>( () => console.log('default ooops') ); 'default ooops' se registra inmediatamente cuando se llama React.useState y se almacena el valor de retorno (en este caso, undefined ).
Esto se puede evitar proporcionando una función de orden superior que devuelva la función que desea almacenar :
const [ooops, setOoops] = React.useState<OoopsFunction>( () => () => console.log('default ooops') ); De esta manera, la función externa se ejecutará definitivamente cuando se ejecute por primera vez React.useState y se almacenará su valor de retorno. Dado que este valor de retorno es ahora su función requerida, esta función se almacenará .
La firma de la función de establecimiento de estado (aquí setOoops ) se da como
Dispatch<SetStateAction<S>>con
type Dispatch<A> = (value: A) => void; type SetStateAction<S> = S | ((prevState: S) => S); Al igual que en React.useState , también existe la posibilidad de actualizar el estado con un valor o una función que devuelve el valor. Entonces, para actualizar el estado, también se debe usar la función de orden superior de arriba .
Las respuestas anteriores me pusieron en el camino correcto, pero necesitaba modificar mis parámetros setState ligeramente porque quería ejecutar una función completa con parámetros. ¡Lo siguiente funcionó para mí!
const [handler, setHandler] = useState(() => {}); setHandler(() => () => enableScheduleById(scheduleId));